/*
 * Su-yun Information Technology, Co.,Ltd CONFIDENTIAL
 *
 * (C) Copyright Su-yun Information Technology, Co.,Ltd. 2021 All Rights Reserved.
 *
 * NOTICE:  All information contained herein is, and remains the property of
 * Su-yun Information Technology, Co.,Ltd. The intellectual property herein
 * are protected by trade secret, patent law or copyright law. Dissemination
 * of this information or reproduction of this material is strictly forbidden
 * unless prior written permission is obtained from Su-yun Information Technology.
 *
 * https://suyunplat.com/
 *
 */
package com.xtiim.battery.discharge.util;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.xtiim.battery.discharge.common.exception.Asserts;
import com.xtiim.battery.discharge.persistence.IPage;
import com.xtiim.battery.discharge.persistence.Page;

import java.util.ArrayList;
import java.util.List;

/**
 * Util for pagination
 *
 */
public class PageUtil {
    /**
     * Manual pagination on given list.
     *
     * @param totalList the overall list
     * @param pageNo page number
     * @param pageSize page size
     * @return the page
     */
    public static <T> IPage<T> doPage(List<T> totalList, Integer pageNo, Integer pageSize) {
        IPage<T> page = new Page<>();

        cn.hutool.core.util.PageUtil.setOneAsFirstPageNo();
        int totalPage = cn.hutool.core.util.PageUtil.totalPage(totalList.size(), pageSize);
        int[] startAndEnd = cn.hutool.core.util.PageUtil.transToStartEnd(pageNo, pageSize);
        List<T> listInPage = ListUtil.sub(totalList, startAndEnd[0], startAndEnd[1]);

        page.setRecords(listInPage);
        page.setTotal(totalList.size());
        page.setPages(totalPage);
        page.setCurrent(pageNo);
        page.setSize(pageSize);

        return page;
    }

    /**
     * Get the total page
     *
     * @param totalSize
     * @param pageSize
     * @return
     */
    public static Integer totalPage(Integer totalSize, Integer pageSize) {
        Integer totalPage = totalSize == 0 ? 0 :
                                (totalSize < pageSize ? 1 :
                                        totalSize % pageSize == 0 ? totalSize / pageSize : totalSize / pageSize + 1);
        return totalPage;
    }

    /**
     * Create an empty page.
     *
     * @param pageNo page number
     * @param pageSize page size
     * @param <T>
     * @return empty page
     */
    public static <T> IPage<T> emptyPage(Integer pageNo, Integer pageSize) {
        IPage<T> page = new Page<>();

        page.setRecords(new ArrayList<T>());
        page.setTotal(0);
        page.setPages(0);
        page.setCurrent(pageNo);
        page.setSize(pageSize);

        return page;
    }

    /**
     * Convert {@link Page<T1>} into {@link Page<T2>}
     *
     * @param page original page of T1
     * @param records records contained in page of T2
     * @param <T1> T1 type
     * @param <T2> T2 type
     * @return {@link Page<T2>} instance
     */
    public static <T1, T2> IPage<T2> convert(IPage<T1> page, List<T2> records) {
        IPage<T2> resultPage = new Page<>();
        resultPage.setCurrent(page.getCurrent());
        resultPage.setSize(page.getSize());
        resultPage.setPages(page.getPages());
        resultPage.setTotal(page.getTotal());
        resultPage.setRecords(records);

        return resultPage;
    }

    /**
     * Validate page params
     *
     * @param pageNo page number
     * @param pageSize page size
     */
    public static void validatePageParams(Integer pageNo, Integer pageSize) {
        if (pageNo == null || pageNo < 1) {
            Asserts.failInvalidParam("Invalid page number.");
        }

        if (pageSize == null || pageSize < 1) {
            Asserts.failInvalidParam("Invalid page size.");
        }
    }

    /**
     * If page number or page size is valid, convert it.
     * Otherwise, return the default value.
     *
     * @param pageNo
     * @param pageSize
     * @return
     */
    public static Integer[] convertOrDefault(String pageNo, String pageSize) {
        Integer[] pair = new Integer[2];

        pair[0] = StrUtil.isBlank(pageNo) || !NumberUtil.isInteger(pageNo) || Convert.toInt(pageNo) <= 0 ? 1 : Integer.valueOf(pageNo);
        pair[1] = StrUtil.isBlank(pageSize) || !NumberUtil.isInteger(pageSize) || Convert.toInt(pageSize) <= 0 ? 5 : Integer.valueOf(pageSize);

        return pair;
    }
}
